package com.mrlv.redis.aop;

import com.mrlv.redis.annotation.RedisSelect;
import com.mrlv.redis.select.RedisSelectSupport;
import com.mrlv.redis.select.SelectableRedisTemplate;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**
 * Redis切面处理类
 * @author Mrlv
 * @date 2021年12月19日 16:01
 */
@Aspect
@Component
@ConditionalOnBean(SelectableRedisTemplate.class)
@Slf4j
public class RedisAspect {

    @Value("${spring.redis.database:0}")
    private int defaultDataBase;

    /**
     * 环绕增强标注 RedisUtils 调用set get 的方法
     * @author Mrlv
     * @date 2021/12/19 16:15
     * @param point
     * @return java.lang.Object
     */
    @Around("execution(* com.mrlv.redis.utils.RedisUtils.*(..))")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        Object result = null;
        try {
            result = point.proceed();
        } catch (Exception e){
            log.error("Redis Error", e);
            throw new RuntimeException("Redis服务异常");
        }
        return result;
    }

    /**
     * 环绕增强标注 RedisSelect 注解的方法
     * @author Mrlv
     * @date 2021/12/19 16:15
     * @param point
     * @return java.lang.Object
     */
    @Around("@annotation(com.mrlv.redis.annotation.RedisSelect)")
    @ConditionalOnBean(SelectableRedisTemplate.class)
    public Object configRedis(ProceedingJoinPoint point) throws Throwable{
        int db = defaultDataBase;
        try {
            MethodSignature signature = (MethodSignature) point.getSignature();
            Method method = signature.getMethod();
            RedisSelect config = method.getAnnotation(RedisSelect.class);
            if(config != null){
                db = config.value();
            }
            RedisSelectSupport.select(db);
            return point.proceed();
        } finally {
            //在环绕通知执行回调完成后 重置 RedisSelectSupport 中的静态 db
            RedisSelectSupport.select(defaultDataBase);
            //logger.debug("redis 重置db {} 到 {}", db, defaultDataBase);
        }
    }
}